package com.shark.lib.rebirth;

import android.app.ActivityManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import me.weishu.reflection.Reflection;

public class RebirthEnv {

    private static final String TAG = "RebirthEnv";
    public static final String ACTION_START_JOB_ALARM_SUB = "com.shark.START_JOB_ALARM_SUB";
    public static final String ACTION_CANCEL_JOB_ALARM_SUB = "com.shark.CANCEL_JOB_ALARM_SUB";
    public static final int DEFAULT_WAKE_UP_INTERVAL = 2 * 60 * 1000; // 默认JobScheduler 唤醒时间为 2 分钟
    public static final int MINIMAL_WAKE_UP_INTERVAL = 60 * 1000; // 最小时间为 1 分钟
    private static volatile IRebirthProcess mDaemonStrategy;

    RebirthEnvConfigs mConfigurations;
    static RebirthEnv client;

    private RebirthEnv(RebirthEnvConfigs configurations) {
        this.mConfigurations = configurations;
    }

    public static void init(Context base, RebirthEnvConfigs configurations) {
        Reflection.unseal(base);
        client = new RebirthEnv(configurations);
        client.initDaemon(base);
    }

    public static void triggerDaemonDead() {
        if (mDaemonStrategy != null) {
            mDaemonStrategy.onDaemonDead();
        }
    }

    public static int getWakeUpInterval(int sWakeUpInterval) {
        return Math.max(sWakeUpInterval, MINIMAL_WAKE_UP_INTERVAL);
    }

    public static void startServiceMayBind(@NonNull final Context context,
                                           @NonNull final Class<? extends Service> serviceClass,
                                           @NonNull AbsServiceConnection connection) {

        // 判断当前绑定的状态
        if (!connection.mConnectedState) {
            Log.d(TAG, "启动并绑定服务 ：" + serviceClass.getSimpleName());
            final Intent intent = new Intent(context, serviceClass);
            startServiceSafely(context, serviceClass);
            context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
        }
    }

    public static void startServiceSafely(Context context, Class<? extends Service> i) {
        Log.d(TAG, "安全启动服务...: " + i.getSimpleName());
        try {
            if (Build.VERSION.SDK_INT >= 26) {
                context.startForegroundService(new Intent(context, i));
            } else {
                context.startService(new Intent(context, i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void safelyUnbindService(Service service, AbsServiceConnection mConnection) {
        try {
            if (mConnection.mConnectedState) {
                service.unbindService(mConnection);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void initDaemon(Context base) {
        if (mConfigurations == null) {
            return;
        }

        if (mDaemonStrategy == null) {
            initDaemonProcess();
        }

        String processName = getProcessName();
        String packageName = base.getPackageName();
        if (processName == null) {
            Log.e(TAG, "process name is empty");
        } else if (processName.startsWith(mConfigurations.PERSISTENT_CONFIG.processName)) {
            mDaemonStrategy.onPersistentCreate(base, mConfigurations);
        } else if (processName.startsWith(mConfigurations.DAEMON_ASSISTANT_CONFIG.processName)) {
            mDaemonStrategy.onDaemonAssistantCreate(base, mConfigurations);
        } else if (processName.startsWith(packageName)) {
            mDaemonStrategy.onInit(base, mConfigurations);
        }
    }

    public static void bindDaemonService(Context context, AbsServiceConnection connection) {
        if (!needStartDaemon(context)) {
            return;
        }

        if (client != null && client.mConfigurations != null) {
            String processName = client.getProcessName();
            RebirthEnvConfigs mConfigs = client.mConfigurations;
            Log.e(TAG, "bindDaemonService: " + processName);

            if (processName == null) {
                return;
            }
            if (processName.startsWith(mConfigs.PERSISTENT_CONFIG.processName)) {
                startServiceMayBind(context, mConfigs.DAEMON_ASSISTANT_CONFIG.serviceClass, connection);
            } else if (processName.startsWith(mConfigs.DAEMON_ASSISTANT_CONFIG.processName)) {
                startServiceMayBind(context, mConfigs.PERSISTENT_CONFIG.serviceClass, connection);
            }
        }
    }

    /**
     * 通知进程开始工作
     */
    public static void sendStartWorkBroadcast(Context context, Class<? extends Service> serviceClass) {
        Log.d("Rebirth", "发送开始广播...");
        if (client == null) {
            Log.e("Rebirth", "请先进行全局初始化...");
            return;
        }
        setNeedStartSDaemon(context, true);
        if (!client.isProcessRunning(serviceClass.getName())) {
            startServiceSafely(context, serviceClass);
        } else {
            context.sendBroadcast(new Intent(ACTION_START_JOB_ALARM_SUB));
        }
    }

    /**
     * 通知进程停止工作
     */
    public static void sendStopWorkBroadcast(Context context) {
        Log.d("Rebirth", "发送停止广播...");
        setNeedStartSDaemon(context, false);
        context.sendBroadcast(new Intent(ACTION_CANCEL_JOB_ALARM_SUB));
    }


    private static final String REBIRTH_SHARED_UTILS = "REBIRTH_SHARED_UTILS";

    private static final String KEY_NEED_START_DAEMON = "need_start_sport";

    public static void setNeedStartSDaemon(Context context, boolean mapType) {
        context.getSharedPreferences(REBIRTH_SHARED_UTILS, Context.MODE_MULTI_PROCESS).edit().putBoolean(KEY_NEED_START_DAEMON, mapType).commit();
    }

    public static boolean needStartDaemon(Context context) {
        return context.getSharedPreferences(REBIRTH_SHARED_UTILS, Context.MODE_MULTI_PROCESS).getBoolean(KEY_NEED_START_DAEMON, false);
    }

    private IRebirthProcess.OnDaemonDeadListener listener
            = new IRebirthProcess.OnDaemonDeadListener() {
        @Override
        public void onDaemonMaybeDead() {
            Log.e(TAG, "onDaemonMaybeDead..." );
        }
    };

    private void initDaemonProcess() {
        mDaemonStrategy = new RebirthProcessImpl();
        mDaemonStrategy.setOnDaemonDeadListener(listener);
    }

    private boolean isProcessRunning(String serviceName) {
        BufferedReader mBufferedReader = null;
        String mReader = null;
        try {
            File file = new File("/proc/self/cmdline");
            mBufferedReader = new BufferedReader(new FileReader(file));
            while ((mReader = mBufferedReader.readLine()) != null) {
                if (mReader.trim().startsWith(serviceName)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (mBufferedReader != null) {
                try {
                    mBufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private String getProcessName() {
        BufferedReader mBufferedReader = null;
        String mReader = null;
        try {
            File file = new File("/proc/self/cmdline");
            mBufferedReader = new BufferedReader(new FileReader(file));
            if ((mReader = mBufferedReader.readLine()) != null) {
                return mReader.trim();
            }else{
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (mBufferedReader != null) {
                try {
                    mBufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
